package com.allwees.bs.c.module.order.dto;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.allwees.bs.c.module.order.entity.LogisticsWaybillEntity;
import com.allwees.bs.c.module.order.entity.OrderEntity;
import com.allwees.bs.c.module.order.entity.OrderFlowEntity;
import com.allwees.bs.c.module.order.entity.OrderItemEntity;
import com.allwees.bs.c.module.order.entity.OrderRefundEntity;
import com.allwees.bs.c.module.order.entity.OrderSkuSnapEntity;
import com.allwees.bs.c.module.user.dto.UserDto;
import com.allwees.bs.core.model.order.wf.order.EOrderItemAction;
import com.allwees.bs.core.model.order.wf.order.EOrderItemState;
import com.allwees.bs.core.model.order.wf.order.EOrderState;
import com.allwees.bs.core.model.payment.enums.EPaymentType;
import com.allwees.core.common.constant.EPlatform;
import com.allwees.core.common.util.reflect.PojoUtil;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Getter
@Setter
//@ApiModel
public class OrderDTO implements Serializable {
    private String uuid;

    // 订单编号
    private String no;

    private String userUuid;

    private String retailerUuid;

    private String storeUuid;

    //订单生成方式,拼团或者单独购买
    private Integer type;

    //订单最大申请退款次数
    private Integer refundMax;

    // 购买数量
    private Integer sum;

    // 订单总金额
    private BigDecimal amt;

    // 现金金额
    private BigDecimal amtCash;

    // 商品总价
    private BigDecimal amtProduct;

    // 商品优惠金额
    private BigDecimal amtProductCoupon;

    /** 平台订单金额 */
    protected BigDecimal platformAmt;

    // 运费
    private BigDecimal amtShipping;

    // 订单总金额币种
    private String currency;

    // 订单上一个状态,当出现需要回滚状态时使用
//    private EOrderState backState;

    // 订单当前状态
    private EOrderState state;

    // 最后一个动作
//    private EOrderAction latestAction;

    // 收货地址ID
    private String shippingAddressUuid;

    // 收货地址
    private OrderShippingAddress shippingAddress;

    // 支付方式
    private EPaymentType paymentType;

    // 支付账号ID，默认为空，只有在支付方式是信用卡时才会使用
    private String paymentUuid;

    //支付过期时间
    private Date paymentExpiredAt;

    //支付时间
    private Date paymentAt;

    private boolean payed = false;

    //订单关闭时间
    private Date closedAt;

    private Integer weight;

    private String userCouponUuid;

    private String userCouponNo;

    private String userPromoLogUuid;

    private String promoCode;

    private Date createdAt;

    private Date updatedAt;

    private Date deletedAt;

    private UserDto user;

    private Integer receiveEndDays = 7;

    // 订单明细项
    private List<OrderItemDTO> items;

//    // 退款单
//    private OrderRefundDTO refund;

    //订单流转记录
    private List<OrderFlowDTO> flows;

    //是否可以取消
    private Boolean cancelAble;

    //是否可以支付
    private Boolean payAble;

    //是否可以收货
    private Boolean receiveAble;

    //营业税
    private BigDecimal amtSaleTax;
    /** 营业税(原始总税费) */
    protected BigDecimal originalAmtSaleTax;

    /** 加价后营业税 */
    protected BigDecimal amtSaleTaxAfterAdd;


    private BigDecimal originalAmtShipping;

    private BigDecimal originalAmtProduct;

    private BigDecimal amtProductAfterAdd;

    private BigDecimal amtShippingAfterAdd;

    private String mainPhoto;

    protected Integer isInfluencer;

    /**
     * 是否是新用户购买
     */
    @JsonIgnore
    @JSONField(serialize = false)
    protected Boolean newUser;

    @JsonIgnore
    @JSONField(serialize = false)
    private transient EPlatform platform;

    public OrderDTO() {
    }

    public OrderDTO(OrderEntity order, List<OrderFlowEntity> orderFlows) {
        //订单信息
        BeanUtils.copyProperties(order, this);
        this.setState(order.getState());

        // flows
        setOrderFlows(orderFlows);

        //权限按钮
        handleAble(order);

        //收货地址
        this.setShippingAddress(new OrderShippingAddress(order));
    }

    public OrderDTO setOrderItems(List<OrderItemEntity> items, List<OrderSkuSnapEntity> skuSnaps, List<LogisticsWaybillEntity> orderLogistics, Map<String, OrderRefundEntity> refundMap) {
        Map<String, LogisticsWaybillEntity> logisticsMap = orderLogistics.stream().collect(Collectors.toMap(LogisticsWaybillEntity::getOrderItemUuid, o -> o));
        Map<String, OrderSkuSnapEntity> skuSnapMap = skuSnaps.stream().collect(Collectors.toMap(OrderSkuSnapEntity::getOrderItemUuid, o -> o));
        if (null == items) {
            return null;
        }
        this.items = new ArrayList<>(items.size());
        items.forEach(item -> this.items.add(new OrderItemDTO(item, skuSnapMap.get(item.getUuid()), logisticsMap.get(item.getUuid())).setRefundInfo(refundMap.get(item.getUuid()))));
        return this;
    }

    public OrderDTO setOrderFlows(List<OrderFlowEntity> orderFlows) {
        if (CollectionUtils.isEmpty(orderFlows)) {
            return this;
        }
        // flows
        this.flows = new ArrayList<>(orderFlows.size());

        //todo zhouyw 移除OrderFlows
        //orderFlows.forEach(flow -> this.flows.add(new OrderFlowDTO(flow)));
        return this;
    }


//    /**
//     * 因为订单只能获取自己的，所以不用包含用户信息
//     * 但必须包含商品信息，商品SKU信息，收货地址信息，所以这些数据直接初始化
//     */
//	public OrderDTO(OrderEntity entity) {
//		this.setUuid(entity.getUuid());
//        this.setNo(entity.getNo());
//		this.setUserCouponUuid(entity.getUserCouponUuid());
//		this.setUserUuid(entity.getUserUuid());
//		this.setShippingAddress(new OrderShippingAddress(entity));
//		this.setType(entity.getType());
//		this.setRefundMax(entity.getRefundMax());
//		this.setSum(entity.getSum());
//
//		this.setAmt(entity.getAmt());
//		this.setAmtProduct(entity.getAmtProduct());
//        this.setAmtProductCoupon(entity.getAmtProductCoupon());
//		this.setAmtShipping(entity.getAmtShipping());
//		this.setCurrency(entity.getCurrency());
//
//		this.setBackState(entity.getBackState());
//		this.setState(entity.getState());
//		this.setLatestAction(entity.getLatestAction());
//
//		this.setWeight(entity.getWeight());
//
//		this.setShippingAt(entity.getShippingAt());
//		this.setDeliverAt(entity.getDeliverAt());
//
//		this.setPaymentType(entity.getPaymentType());
//		this.setPaymentUuid(entity.getPaymentUuid());
//		this.setPaymentExpiredAt(entity.getPaymentExpiredAt());
//		this.setPaymentAt(entity.getPaymentAt());
//
//		this.setConfirmedShippingAt(entity.getConfirmedShippingAt());
//		this.setClosedAt(entity.getClosedAt());
//		this.setCreatedAt(entity.getCreatedAt());
//		this.setUpdatedAt(entity.getUpdatedAt());
//		this.setDeletedAt(entity.getDeletedAt());
//		this.setReviewAble(entity.reviewAble());
//
//        this.setAmtSaleTax(entity.getAmtSaleTax());
//        this.setAmtShippingInsurance(entity.getAmtShippingInsurance());
//        this.setOriginalAmtShipping(entity.getOriginalAmtShipping());
//        this.setOriginalAmtProduct(entity.getOriginalAmtProduct());
//
//        this.setExpressCode(entity.getExpressCode());
//        if(StringUtils.isNotBlank(entity.getExpressCode())) {
//            OrderLogisticsDTO orderLogistic = BeanUtil.getBean(IOrderLogisticsService.class).findByExpressCode(entity.getExpressCode());
//            this.setOrderLogistic(orderLogistic);
//        }
//
//        if(entity.getFlows() != null) {
//			this.flows = new ArrayList<>();
//			int size = entity.getFlows().size();
//			for(int i = size - 1; i >= 0; i--) {
//				OrderFlowEntity flowEntity = entity.getFlows().get(i);
//				this.getFlows().add(new OrderFlowDTO(flowEntity));
//			}
//		}
//
////		this.setRefund(new OrderRefundDTO(entity));
////		this.setRefundState(this.getRefund().getState());
//		// 判断订单是否能退款
//        handleAble(entity);
//
//		if(entity.getItems() != null) {
//			this.items = new ArrayList<>();
//			entity.getItems().forEach(item -> this.items.add(new OrderItemDTO(item)));
//		}
//	}

    public void handleAble(OrderEntity order) {
        EOrderState orderState = order.getState();

//        this.setReviewAble(order.reviewAble());
//	    this.setRefundAble(refundAble(order));
        this.setCancelAble(cancelAble(orderState));
        this.setReceiveAble(receiveAble(orderState));
        this.setPayed(order.getPayed() == null ? false : order.getPayed());
        this.setPayAble(payAble(orderState));
    }

//    private boolean refundAble(OrderEntity order) {
//        if(order.getRefundMax() == 0) {
//            return false;
//        } else {
//            if (!order.getRefundMax().equals(order.getRefundCount()) && order.refundStatusAble()) {
//                return true;
//            } else {
//                return false;
//            }
//        }
//    }

    private boolean cancelAble(EOrderState orderState) {
        return EOrderState.CREATED.equals(orderState);
    }

    private boolean payAble(EOrderState orderState) {
        return EOrderState.CREATED.equals(orderState);
    }

    private boolean receiveAble(EOrderState orderState) {
        //return EOrderState.SHIPPED.equals(orderState);
        return EOrderState.DELIVERED.equals(orderState);
    }

    public boolean isAmtPayedOfCoupon() {
        return BigDecimal.ZERO.compareTo(amt) == 0;
    }

//    private boolean payed(EOrderItemState orderState) {
//        return !EOrderItemState.CREATED.equals(orderState);
//    }
//
//    private boolean receiveEndDaysAble(EOrderItemState orderState) {
//	    return false;
//        return !EOrderState.SHIPPED.equals(orderState);
//    }

    public Long getDownTime() {
        if (!payAble(this.state)) {
            return 0L;
        }
        long downTime = paymentExpiredAt.getTime() - System.currentTimeMillis();
        return downTime >= 0 ? downTime : 0L;
    }

    public String getStateDesc() {
        if (state != null) {
            return state.customerDesc();
        }
        return StringUtils.EMPTY;
    }

    @Data
    private static class OrderFlowDTO {
        //ID
        private String uuid;

        //订单ID
        private String orderUuid;

        //动作
        private EOrderItemAction action;

        //订单上一个状态
        private EOrderItemState backState;

        //订单当前状态
        private EOrderItemState state;

        //类型
        private Integer type;

        //原因
        private Integer reason;

        //备注 如不予退款的原因
        private String remark;

        //图片
        private String[] photos;

        //创建时间
        private Date createdAt;

        //支付状态
        private Integer paymentState = 0;

        public OrderFlowDTO() {
        }

        private OrderFlowDTO(OrderFlowEntity entity) {
            this();
            PojoUtil.copy(this, entity);
        }
    }

    @Data
    public static class OrderShippingAddress {
//        @ApiModelProperty(value = "名")
        private String firstName;

//        @ApiModelProperty(value = "姓")
        private String lastName;

//        @ApiModelProperty(value = "国际电话区号")
        private String itu;

//        @ApiModelProperty(value = "电话号码")
        private String phone;

//        @ApiModelProperty(value = "国家")
        private String country;

//        @ApiModelProperty(value = "州/省")
        private String province;

//        @ApiModelProperty(value = "城市")
        private String city;

//        @ApiModelProperty(value = "区号")
        private String zipCode;

//        @ApiModelProperty(value = "地址第一行")
        private String addressLine1;

//        @ApiModelProperty(value = "地址第二行")
        private String addressLine2;

        private String note;

        private OrderShippingAddress(OrderEntity entity) {
            this.setFirstName(entity.getShippingAddressFirstName());
            this.setLastName(entity.getShippingAddressLastName());
            this.setItu(entity.getShippingAddressItu());
            this.setPhone(entity.getShippingAddressPhone());
            this.setCountry(entity.getShippingAddressCountry());
            this.setProvince(entity.getShippingAddressProvince());
            this.setCity(entity.getShippingAddressCity());
            this.setZipCode(entity.getShippingAddressZipCode());
            this.setAddressLine1(entity.getShippingAddressLine1());
            this.setAddressLine2(entity.getShippingAddressLine2());
            this.setNote(entity.getNote());
        }
    }
}
